﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace net.xBei.Helper
{
    /// <summary>
    /// 数学、数字处理相关
    /// </summary>
    public static class MathHelper
    {
        /// <summary>
        /// 数字转字符串
        /// </summary>
        /// <param name="num"></param>
        /// <param name="radix"></param>
        /// <returns></returns>
        public static string ToString(this float num, int radix)
        {
            var s = $"{num}".Split(".", StringSplitOptions.RemoveEmptyEntries);
            if (s.Length <= 1) return s[0];
            return $"{s[0]}.{s[1].Substring(0, Math.Min(radix, s[1].Length))}";
        }
 
        #region 字符串转数字
        #region 整形
        /// <summary>
        /// 字符串转无符号整形（32位）
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static uint GetUInt(this string txt, uint dv = 0)
            => uint.TryParse(txt, out var r) ? r : dv;
        /// <summary>
        /// 字符串转整形（32位）
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static int GetInt(this string txt, int dv = 0)
            => int.TryParse(txt, out var r) ? r : dv;
        public static int GetInt(this object obj, int dv = 0) {
            if (obj == null) return dv;
            if (obj is string str) {
                return int.TryParse(str, out var r) ? r : dv;
            }
            if (obj is uint uintObj) {
                return (int)uintObj;
            }
            if (obj is int intObj) {
                return intObj;
            }
            if (obj is ulong ulongObj) {
                return (int)ulongObj;
            }
            if (obj is long longObj) {
                return (int)longObj;
            }
            if (obj is float floatObj) {
                return (int)floatObj;
            }
            if (obj is double doubleObj) {
                return (int)doubleObj;
            }
            if (obj is decimal decimalObj) {
                return (int)decimalObj;
            }
            return dv;
        }
        /// <summary>
        /// 字符串转无符号整形（64位）
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static ulong GetULong(this string txt, ulong dv = 0)
            => ulong.TryParse(txt, out var r) ? r : dv;
        /// <summary>
        /// 字符串转整形（64位）
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static long GetLong(this string txt, long dv = 0)
            => long.TryParse(txt, out var r) ? r : dv;
        public static long GetLong(this object obj, long dv = 0) {
            if (obj == null) return dv;
            if (obj is string str) {
                return long.TryParse(str, out var r) ? r : dv;
            }
            if (obj is uint uintObj) {
                return (long)uintObj;
            }
            if (obj is int intObj) {
                return intObj;
            }
            if (obj is ulong ulongObj) {
                return (long)ulongObj;
            }
            if (obj is long longObj) {
                return longObj;
            }
            if (obj is float floatObj) {
                return (long)floatObj;
            }
            if (obj is double doubleObj) {
                return (long)doubleObj;
            }
            if (obj is decimal decimalObj) {
                return (long)decimalObj;
            }
            return dv;
        }
        #endregion
        #region 浮点
        /// <summary>
        /// 字符串转浮点（32位）
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static float GetFloat(this string txt, float dv = 0)
            => float.TryParse(txt, out var r) ? r : dv;
        /// <summary>
        /// 字符串转浮点（64位）
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static double GetDouble(this string txt, double dv = 0)
            => double.TryParse(txt, out var r) ? r : dv;
        /// <summary>
        /// 字符串转浮点（128位）
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static decimal GetDecimal(this string txt, decimal dv = 0)
            => decimal.TryParse(txt, out var r) ? r : dv;
        public static decimal GetDecimal(this object obj, decimal dv = 0) {
            if (obj == null) return dv;
            if (obj is string str) {
                return decimal.TryParse(str, out var r) ? r : dv;
            }
            if (obj is uint uintObj) {
                return (decimal)uintObj;
            }
            if (obj is int intObj) {
                return (decimal)intObj;
            }
            if (obj is ulong ulongObj) {
                return (decimal)ulongObj;
            }
            if (obj is long longObj) {
                return (decimal) longObj;
            }
            if (obj is float floatObj) {
                return (decimal) floatObj;
            }
            if (obj is double doubleObj) {
                return (decimal) doubleObj;
            }
            if (obj is decimal decimalObj) {
                return decimalObj;
            }
            return dv;
        }
        #endregion
        #endregion
        #region 位运算
        public static bool HasFlag(this int num, int flag) => (num & flag) == flag;
        #endregion
        /// <summary>
        /// 是否是整数（没有小数点）
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static bool IsInteger(this double num) => num == (int)num;
        public static bool IsNotInteger(this double num) => num != (int)num;
    }
}
